import { Op } from 'sequelize';
import { db, models } from '../../db';
import type { UserInfo } from '../types';

const {
  config_hero: ConfigHeroModel,
  config_item: ConfigItemModel,
  config_exp: ConfigExpModel,
  user: UserModel,
  user_hero: UserHeroModel,
  user_item: UserItemModel,
  user_log_gold: UserLogGoldModel,
  user_log_assets: UserLogAssetsModel,
} = models;

export const recruitRole = async (user_id: string, data: Record<string, any>) => {
  const transaction = await db.transaction();

  return new Promise(async (resolve, reject) => {
    try {
      if (!data) {
        return reject('参数错误');
      }

      const { type } = data;

      if (type !== 1 && type !== 10) {
        return reject('参数错误');
      }

      const userInfo = await UserModel.findOne({ where: { id: user_id } });

      if (!userInfo) {
        return reject(`${user_id}用户不存在`);
      }

      const { gold } = userInfo.dataValues as UserInfo;

      if (type === 1 && gold < 100) {
        return reject('金币不足');
      }

      if (type === 10 && gold < 2800) {
        return reject('金币不足');
      }

      const heros = await ConfigHeroModel.findAll({ where: { can_get: 1 } });
      const heroList: Record<string, any>[] = heros.map(v => v.dataValues);

      const getList: any[] = [];

      for (let index = 0; index < type; index++) {
        const num = Math.floor(Math.random() * 10 + 1);

        if (num === 1) {
          const canRecruit = heroList.filter(v => v.rarity === 6);
          getList.push(canRecruit[Math.floor(Math.random() * canRecruit.length)]);
        }
        if (num > 1 && num <= 3) {
          const canRecruit = heroList.filter(v => v.rarity === 5);
          getList.push(canRecruit[Math.floor(Math.random() * canRecruit.length)]);
        }
        if (num > 3 && num <= 6) {
          const canRecruit = heroList.filter(v => v.rarity === 4);
          getList.push(canRecruit[Math.floor(Math.random() * canRecruit.length)]);
        }
        if (num > 6) {
          const canRecruit = heroList.filter(v => v.rarity < 4);
          getList.push(canRecruit[Math.floor(Math.random() * canRecruit.length)]);
        }
      }

      const res: any[] = [];

      const userRole = await UserHeroModel.findAll({
        where: { user_id },
      });

      const userHeroIdList: number[] = userRole.map(v => {
        return v.dataValues.hero_id;
      });

      getList.forEach(async (v: any) => {
        const { id, rarity } = v;
        // 判断是否拥有该英雄
        const define = userHeroIdList.includes(id);
        if (define) {
          // 如果拥有该英雄, 转化为一定数量的魂魄
          const goodsId = 1000 + rarity;
          const count = Math.pow(2, rarity) * 10;
          res.push({
            id: goodsId,
            count,
          });
        } else {
          userHeroIdList.push(id);
          // 添加英雄
          res.push({
            id: id,
            count: 1,
          });
        }
      });

      // 操作库
      const heroCreater = res
        .filter(v => v.id < 1000)
        .map(v => {
          return {
            user_id,
            hero_id: v.id,
          };
        });

      const goodsCreater = res
        .filter(v => v.id >= 1000)
        .map(v => {
          return {
            user_id,
            item_id: v.id,
            count: v.count,
          };
        });

      await UserModel.update(
        {
          gold: type === 1 ? gold - 300 : gold - 2800,
        },
        { where: { id: user_id }, transaction },
      );

      await UserLogGoldModel.create(
        {
          user_id,
          type: 'use',
          count: type === 1 ? 300 : 2800,
          reason_type: 'recruit',
          reason: '招募英雄',
        },
        { transaction },
      );

      const userHeros = await UserHeroModel.bulkCreate(heroCreater, {
        transaction,
      });

      const userHeroAsstes = userHeros.map(v => {
        return {
          user_id,
          type: 'get',
          assets_id: v.dataValues.id,
          assets_type: 'hero',
          count: 1,
          reason_type: 'recruit',
          reason: '招募英雄',
        };
      });

      await UserLogAssetsModel.bulkCreate(userHeroAsstes, {
        transaction,
      });

      for (let index = 0; index < goodsCreater.length; index++) {
        const item = goodsCreater[index];
        const userItem = await UserItemModel.findOne({
          where: { user_id, item_id: item.item_id },
          transaction,
        });

        if (userItem) {
          await UserItemModel.update(
            {
              count: userItem.dataValues.count + item.count,
            },
            { where: { id: userItem.dataValues.id }, transaction },
          );
          await UserLogAssetsModel.create(
            {
              user_id,
              type: 'get',
              assets_id: userItem.dataValues.id,
              assets_type: 'item',
              count: item.count,
              reason_type: 'recruit',
              reason: '招募英雄',
            },
            { transaction },
          );
        } else {
          const newUserItem = await UserItemModel.upsert(
            {
              user_id,
              item_id: item.item_id,
              count: item.count,
            },
            {
              transaction,
            },
          );

          const { id: newItemId } = newUserItem[0].dataValues;

          await UserLogAssetsModel.create(
            {
              user_id,
              type: 'get',
              assets_id: newItemId,
              assets_type: 'item',
              count: item.count,
              reason_type: 'recruit',
              reason: '招募英雄',
            },
            { transaction },
          );
        }
      }

      await transaction.commit();
      resolve(res);
    } catch (error) {
      console.log(error);
      await transaction.rollback();
    }
  });
};

export const upgradeRole = async (user_id: string, data: Record<string, any>) => {
  return new Promise(async (resolve, reject) => {
    const transaction = await db.transaction();
    try {
      const { id, num, script } = data;
      const upgradeGoods = await ConfigItemModel.findOne({
        where: { script },
      });

      if (!upgradeGoods) {
        return reject('道具不存在');
      }

      const { id: goodsId, params } = upgradeGoods.dataValues;

      const userItem = await UserItemModel.findOne({
        where: { user_id, item_id: goodsId },
      });

      if (!userItem || userItem.dataValues.is_enabled === 0 || userItem.dataValues.count < num) {
        return reject('道具不足');
      }

      const userRole = await UserHeroModel.findOne({
        where: { user_id, id },
      });

      if (!userRole) {
        return reject('英雄不存在');
      }

      const { id: roleId, exp } = userRole.dataValues;

      const newExp = num * params + exp;

      const newLevel = await ConfigExpModel.findOne({
        where: {
          exp: {
            [Op.lte]: newExp,
          },
        },
        order: [['exp', 'DESC']],
      });

      await UserHeroModel.update(
        {
          level: newLevel?.dataValues.id,
          exp: newExp,
        },
        {
          where: { id: roleId },
          transaction,
        },
      );

      const { id: userItemId, count } = userItem.dataValues;
      await UserItemModel.update(
        {
          count: count - num,
        },
        {
          where: { id: userItemId },
          transaction,
        },
      );

      await UserLogAssetsModel.create(
        {
          user_id,
          type: 'use',
          assets_id: userItemId,
          assets_type: 'item',
          count: num,
          reason_type: 'upgrade',
          reason: '升级英雄',
        },
        { transaction },
      );

      await transaction.commit();
      resolve('ok');
    } catch (error) {
      console.log(error);
      await transaction.rollback();
    }
  });
};
